package edu.northwestern.cbits.purple_robot_manager.snapshots; import java.io.File; import java.io.IOException; import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.content.ContentValues; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.media.MediaRecorder; import android.preference.PreferenceManager; import android.widget.Toast; import edu.northwestern.cbits.purple_robot_manager.R; import edu.northwestern.cbits.purple_robot_manager.RobotContentProvider; import edu.northwestern.cbits.purple_robot_manager.activities.settings.SettingsActivity; import edu.northwestern.cbits.purple_robot_manager.logging.LogManager; import edu.northwestern.cbits.purple_robot_manager.probes.Probe; import edu.northwestern.cbits.purple_robot_manager.probes.ProbeManager; public class SnapshotManager { private static final String PROBE_NAME = "probe"; private static final String RECORDED = "recorded"; private static final String VALUE = "value"; private static final String RECORD_AUDIO = "config_record_snapshot_audio"; private static final boolean DEFAULT_RECORD = false; private static SnapshotManager _instance = null; private Context _context = null; private boolean _isRecording = false; private SnapshotManager(Context context) { if (SnapshotManager._instance != null) throw new IllegalStateException("Already instantiated"); this._context = context; } public static SnapshotManager getInstance(Context context) { if (SnapshotManager._instance == null) { SnapshotManager._instance = new SnapshotManager(context.getApplicationContext()); } return SnapshotManager._instance; } public long takeSnapshot(final Context context, String source, final Runnable r) throws EmptySnapshotException { final long now = System.currentTimeMillis(); Cursor cursor = this._context.getContentResolver().query(RobotContentProvider.RECENT_PROBE_VALUES, null, null, null, "recorded DESC"); JSONArray snapshot = new JSONArray(); if (cursor.getCount() == 0) throw new EmptySnapshotException(); while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndex("source")); long recorded = cursor.getLong(cursor.getColumnIndex("recorded")); String value = cursor.getString(cursor.getColumnIndex("value")); try { JSONObject sensorValue = new JSONObject(value); JSONObject sensorObj = new JSONObject(); sensorObj.put(SnapshotManager.PROBE_NAME, name); sensorObj.put(SnapshotManager.RECORDED, recorded); sensorObj.put(SnapshotManager.VALUE, sensorValue); snapshot.put(sensorObj); } catch (JSONException e) { LogManager.getInstance(this._context).logException(e); } } cursor.close(); final ContentValues values = new ContentValues(); values.put("_id", now); values.put("source", source); values.put("recorded", now); values.put("value", snapshot.toString()); final SnapshotManager me = this; final Runnable save = new Runnable() { public void run() { me._context.getContentResolver().insert(RobotContentProvider.SNAPSHOTS, values); if (r != null) r.run(); } }; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this._context); if (this._isRecording == false && prefs.getBoolean(SnapshotManager.RECORD_AUDIO, SnapshotManager.DEFAULT_RECORD)) { this._isRecording = true; if (context instanceof Activity) { final Activity a = (Activity) context; a.runOnUiThread(new Runnable() { public void run() { Toast.makeText(a, R.string.toast_recording_audio, Toast.LENGTH_LONG).show(); } }); } Runnable record = new Runnable() { public void run() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(me._context); File internalStorage = me._context.getCacheDir(); if (SettingsActivity.useExternalStorage(context)) internalStorage = me._context.getExternalCacheDir(); if (internalStorage != null && !internalStorage.exists()) internalStorage.mkdirs(); File audioFolder = new File(internalStorage, "Snapshot Audio"); if (audioFolder != null && !audioFolder.exists()) audioFolder.mkdirs(); File audioFile = new File(audioFolder, now + ".3gp"); final String filename = audioFile.getAbsolutePath(); final MediaRecorder recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setOutputFile(filename); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); try { recorder.prepare(); recorder.start(); Runnable stop = new Runnable() { public void run() { try { Thread.sleep(5000); // TODO: Make // configurable... } catch (InterruptedException e) { } recorder.stop(); recorder.release(); values.put("audio_file", filename); me._isRecording = false; save.run(); } }; Thread stopThread = new Thread(stop); stopThread.start(); } catch (IOException e) { LogManager.getInstance(me._context).logException(e); me._isRecording = false; save.run(); } } }; Thread t = new Thread(record); t.start(); } else save.run(); return now; } public long[] snapshotTimes() { Cursor c = this._context.getContentResolver().query(RobotContentProvider.SNAPSHOTS, null, null, null, "recorded"); long[] times = new long[c.getCount()]; for (int i = 0; c.moveToNext(); i++) { times[i] = c.getLong(c.getColumnIndex("recorded")); } c.close(); return times; } public JSONObject jsonForTime(long time, boolean includeValues) { JSONObject object = new JSONObject(); String selection = "recorded = ?"; String[] args = { "" + time }; Cursor c = this._context.getContentResolver().query(RobotContentProvider.SNAPSHOTS, null, selection, args, null); if (c.moveToNext()) { String source = c.getString(c.getColumnIndex("source")); long recorded = c.getLong(c.getColumnIndex("recorded")); String jsonString = c.getString(c.getColumnIndex("value")); String audio = c.getString(c.getColumnIndex("audio_file")); if (audio != null) { File f = new File(audio); if (f.exists() == false) audio = null; } try { object.put("recorded", recorded); object.put("source", source); if (audio != null) object.put("audio", audio.replace("\\/", "/")); if (includeValues) { JSONArray values = new JSONArray(jsonString); for (int i = 0; i < values.length(); i++) { JSONObject value = values.getJSONObject(i); String name = value.getString("probe"); Probe p = ProbeManager.probeForName(name, this._context); if (p != null) value.put("name", p.title(this._context)); } object.put("values", values); } } catch (JSONException e) { LogManager.getInstance(this._context).logException(e); } } else object = null; c.close(); return object; } public void clearTime(long time) { } public void showSnapshot(long time, Map<String, Object> options) { } public void deleteSnapshot(long timestamp) { String selection = "recorded = ?"; String[] args = { "" + timestamp }; this._context.getContentResolver().delete(RobotContentProvider.SNAPSHOTS, selection, args); } }